package com.shuda.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuda.common.dto.PageDTO;
import com.shuda.common.dto.PageResult;
import com.shuda.common.exception.BusinessException;
import com.shuda.common.utils.SecurityUtils;
import com.shuda.system.dto.RoleDTO;
import com.shuda.system.dto.RoleQueryDTO;
import com.shuda.system.entity.RoleEntity;
import com.shuda.system.entity.UserRoleEntity;
import com.shuda.system.mapper.RoleMapper;
import com.shuda.system.mapper.UserRoleMapper;
import com.shuda.system.service.RoleMenuService;
import com.shuda.system.service.RoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色服务实现类
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleEntity> implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMenuService roleMenuService;

    @Override
    public PageResult<RoleDTO> getRolePage(PageDTO pageDTO, RoleQueryDTO queryDTO) {
        Page<RoleEntity> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        
        LambdaQueryWrapper<RoleEntity> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(queryDTO.getRoleName())) {
            wrapper.like(RoleEntity::getRoleName, queryDTO.getRoleName());
        }
        
        if (StringUtils.hasText(queryDTO.getRoleCode())) {
            wrapper.like(RoleEntity::getRoleCode, queryDTO.getRoleCode());
        }
        
        if (queryDTO.getStatus() != null) {
            wrapper.eq(RoleEntity::getStatus, queryDTO.getStatus());
        }
        
        if (StringUtils.hasText(queryDTO.getStartTime())) {
            wrapper.ge(RoleEntity::getCreateTime, queryDTO.getStartTime());
        }
        
        if (StringUtils.hasText(queryDTO.getEndTime())) {
            wrapper.le(RoleEntity::getCreateTime, queryDTO.getEndTime());
        }
        
        wrapper.orderByDesc(RoleEntity::getCreateTime);
        
        IPage<RoleEntity> result = roleMapper.selectPage(page, wrapper);
        
        List<RoleDTO> dtoList = result.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageResult<>(dtoList, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public RoleDTO getRoleById(Long id) {
        RoleEntity entity = roleMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("角色不存在");
        }
        return convertToDTO(entity);
    }

    @Override
    @Transactional
    public Long createRole(RoleDTO roleDTO) {
        RoleEntity entity = convertToEntity(roleDTO);
        entity.setStatus(1); // 默认启用
        entity.setCreateBy(SecurityUtils.getCurrentUsername());
        entity.setCreateTime(LocalDateTime.now());
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        entity.setDeleted(0);
        
        roleMapper.insert(entity);
        return entity.getId();
    }

    @Override
    @Transactional
    public void updateRole(Long id, RoleDTO roleDTO) {
        RoleEntity existingEntity = roleMapper.selectById(id);
        if (existingEntity == null) {
            throw new BusinessException("角色不存在");
        }
        
        RoleEntity entity = convertToEntity(roleDTO);
        entity.setId(id);
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        
        roleMapper.updateById(entity);
    }

    @Override
    @Transactional
    public void deleteRole(Long id) {
        RoleEntity entity = roleMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("角色不存在");
        }
        
        // 删除用户角色关联
        LambdaQueryWrapper<UserRoleEntity> userRoleWrapper = new LambdaQueryWrapper<>();
        userRoleWrapper.eq(UserRoleEntity::getRoleId, id);
        userRoleMapper.delete(userRoleWrapper);
        
        // 逻辑删除角色
        entity.setDeleted(1);
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        roleMapper.updateById(entity);
    }

    @Override
    @Transactional
    public void batchDeleteRole(List<Long> ids) {
        if (ids != null && !ids.isEmpty()) {
            for (Long id : ids) {
                deleteRole(id);
            }
        }
    }

    @Override
    @Transactional
    public void updateRoleStatus(Long id, Integer status) {
        RoleEntity entity = roleMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("角色不存在");
        }
        
        entity.setStatus(status);
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        roleMapper.updateById(entity);
    }

    @Override
    public List<RoleDTO> getAllEnabledRoles() {
        LambdaQueryWrapper<RoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleEntity::getStatus, 1)
                .eq(RoleEntity::getDeleted, 0)
                .orderByDesc(RoleEntity::getSort);
        
        List<RoleEntity> entities = roleMapper.selectList(wrapper);
        return entities.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RoleDTO> getUserRoles(Long userId) {
        LambdaQueryWrapper<UserRoleEntity> userRoleWrapper = new LambdaQueryWrapper<>();
        userRoleWrapper.eq(UserRoleEntity::getUserId, userId);
        
        List<UserRoleEntity> userRoleEntities = userRoleMapper.selectList(userRoleWrapper);
        List<Long> roleIds = userRoleEntities.stream()
                .map(UserRoleEntity::getRoleId)
                .collect(Collectors.toList());
        
        if (roleIds.isEmpty()) {
            return List.of();
        }
        
        LambdaQueryWrapper<RoleEntity> roleWrapper = new LambdaQueryWrapper<>();
        roleWrapper.in(RoleEntity::getId, roleIds)
                .eq(RoleEntity::getStatus, 1)
                .eq(RoleEntity::getDeleted, 0);
        
        List<RoleEntity> entities = roleMapper.selectList(roleWrapper);
        return entities.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void assignUserRoles(Long userId, List<Long> roleIds) {
        // 先删除现有角色关联
        LambdaQueryWrapper<UserRoleEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleEntity::getUserId, userId);
        userRoleMapper.delete(wrapper);
        
        // 添加新的角色关联
        if (roleIds != null && !roleIds.isEmpty()) {
            for (Long roleId : roleIds) {
                UserRoleEntity userRoleEntity = new UserRoleEntity();
                userRoleEntity.setUserId(userId);
                userRoleEntity.setRoleId(roleId);
                userRoleEntity.setCreateBy(SecurityUtils.getCurrentUsername());
                userRoleEntity.setCreateTime(LocalDateTime.now());
                userRoleEntity.setUpdateBy(SecurityUtils.getCurrentUsername());
                userRoleEntity.setUpdateTime(LocalDateTime.now());
                userRoleEntity.setDeleted(0);
                userRoleMapper.insert(userRoleEntity);
            }
        }
    }

    @Override
    public List<Long> getRoleMenuIds(Long roleId) {
        return roleMenuService.getRoleMenuIds(roleId);
    }

    @Override
    @Transactional
    public void assignRoleMenus(Long roleId, List<Long> menuIds) {
        roleMenuService.assignRoleMenus(roleId, menuIds);
    }

    private RoleDTO convertToDTO(RoleEntity entity) {
        RoleDTO dto = new RoleDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    private RoleEntity convertToEntity(RoleDTO dto) {
        RoleEntity entity = new RoleEntity();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }
}